블로그 릴레이 - CDK 로 Amazon Cognito 리소스를 이용해서 Amazon API Gateway에 Authorizer 설정 해보기
안녕하세요 생산지원 그룹 리테일 어플리케이션부의 김승연입니다.
본 블로그는 당사의 한국어 블로그 릴레이의 24번째 블로그입니다.
이번 블로그 주제는 「CDK 로 Amazon Cognito 리소스를 이용해서 Amazon API Gateway에 Authorizer 설정 해보기」 입니다.
개요
이번에는 이전에 작성한 블로그에서 작성한 API에 인증된 사용자만 접속할 수 있도록 Amazon Cognito 리소스를 생성 후 Amazon API Gateway에 Authorizer 설정을 추가해 보았습니다.
코드 작성
이전에 작성한 블로그 릴레이 - CDK 와 Serverless express 사용해 보기의 리소스를 이용해 준비 과정은 빠르게 스킵하고 바로 코드를 작성해 보도록 하겠습니다.
...
// Cognito user pool
const cognitoUserPool = new cdk.aws_cognito.UserPool(this, 'userPool', {
userPoolName: 'userPool',
standardAttributes: { email: { required: true, mutable: false } }, // 이메일 필수・수정 불가
autoVerify: { email: true }, // 이메일 자동 인증
});
cognitoUserPool.addClient('clientCognitoUserPool', {
userPoolClientName: 'clientCognitoUserPool',
authFlows: { adminUserPassword: true, userPassword: true },
});
// Cognito Authorizer
const cognitoUserPoolsAuthorizer =
new aws_apigateway.CognitoUserPoolsAuthorizer(
this,
'CognitoUserPoolsAuthorizer',
{
cognitoUserPools: [cognitoUserPool],
},
);
// Lambda
const restApiFunc = new cdk.aws_lambda_nodejs.NodejsFunction(
this,
'RestApiFunc',
{
architecture: cdk.aws_lambda.Architecture.ARM_64,
runtime: cdk.aws_lambda.Runtime.NODEJS_20_X,
entry: "../server/src/index.ts",
}
);
// APIGateway REST API
const restApi = new cdk.aws_apigateway.LambdaRestApi(this, 'RestApi', {
handler: restApiFunc,
defaultCorsPreflightOptions: {
allowOrigins: cdk.aws_apigateway.Cors.ALL_ORIGINS,
allowMethods: cdk.aws_apigateway.Cors.ALL_METHODS,
allowHeaders: cdk.aws_apigateway.Cors.DEFAULT_HEADERS,
maxAge: cdk.Duration.minutes(5),
},
deployOptions: {
stageName: 'v1',
tracingEnabled: false,
},
defaultMethodOptions: {
authorizer: cognitoUserPoolsAuthorizer, // API Gateway 에 Authorizer 설정
},
});
// API Gateway EndPoint
new cdk.CfnOutput(this, 'RestApiEndpoint', {
value: restApi.deploymentStage.urlForPath(),
});
...
아래의 코드 작성이 완료되었다면 다음으로는 배포 후 실제로 동작 하는지 확인해 보겠습니다.
확인
1.CDK를 Deploy를 해줍니다.
npm run cdk bootstrap ← 최초만 실행
npm run cdk deploy
2.다음으로 실제 리소스 가 생성되어 있는지 확인 후 "사용자 관리"→"사용자" 탭으로 이동 후 사용자를 만듭니다.
3.다음으로 사용자를 생성하였다면 아래를 실행해 Token을 습득합니다.
조금 번거롭지만, Amazon Cognito 에서는 초기 패스워드 변경이 필수 옵션으로 되어 있어, Token 습득을 위해서는 패스워드 변경 과정이 필요합니다.
1.
curl -X POST \
-H "Content-Type: application/x-amz-json-1.1" \
-H "X-Amz-Target: AWSCognitoIdentityProviderService.InitiateAuth" \
-d $'{
"AuthParameters": {
"USERNAME": "유저명",
"PASSWORD": "이메일을 통해 받은 임시 패스워드"
},
"AuthFlow": "USER_PASSWORD_AUTH",
"ClientId": "Amazon cognito clientId"
}' \
https://cognito-idp.[region].amazonaws.com/
2.
curl -X POST \
-H "Content-Type: application/x-amz-json-1.1" \
-H "X-Amz-Target: AWSCognitoIdentityProviderService.RespondToAuthChallenge" \
-d $'{
"ChallengeName": "NEW_PASSWORD_REQUIRED",
"ChallengeResponses": {
"USERNAME": "유저명",
"PASSWORD": "기존의 임시 패스워드",
"NEW_PASSWORD": "새로 설정할 패스워드"
},
"ClientId": "Amazon cognito clientId",
"Session": "위에서 Response 된 Session"
}' \
https://cognito-idp.[region].amazonaws.com/
4.마지막으로 습득한 토큰을 Header에 설정해 확인합니다.
curl -X GET -H "Content-Type: application/json" -H "Authorization: IdToken" https://xxxxxxxx.execute-api.[region].amazonaws.com/v1/...
보충
만약 기존에 작성된 Amazon Cognito 리소스가 있다면 Cognito UserPoolId를 참조 후 설정하셔도 됩니다.
...
// Cognito user pool 참조
const cognitoUserPool = aws_cognito.UserPool.fromUserPoolId(
this,
'UserPool',
'Cognito UserPoolId 지정',
);
// Cognito Authorizer
const cognitoUserPoolsAuthorizer =
new aws_apigateway.CognitoUserPoolsAuthorizer(
this,
'CognitoUserPoolsAuthorizer',
{
cognitoUserPools: [cognitoUserPool],
},
);
// Lambda
const restApiFunc = new cdk.aws_lambda_nodejs.NodejsFunction(
this,
'RestApiFunc',
{
architecture: cdk.aws_lambda.Architecture.ARM_64,
runtime: cdk.aws_lambda.Runtime.NODEJS_20_X,
entry: "../server/src/index.ts",
}
);
// APIGateway REST API
const restApi = new cdk.aws_apigateway.LambdaRestApi(this, 'RestApi', {
handler: restApiFunc,
defaultCorsPreflightOptions: {
allowOrigins: cdk.aws_apigateway.Cors.ALL_ORIGINS,
allowMethods: cdk.aws_apigateway.Cors.ALL_METHODS,
allowHeaders: cdk.aws_apigateway.Cors.DEFAULT_HEADERS,
maxAge: cdk.Duration.minutes(5),
},
deployOptions: {
stageName: 'v1',
tracingEnabled: false,
},
defaultMethodOptions: {
authorizer: cognitoUserPoolsAuthorizer, // API Gateway 에 Authorizer 설정
},
});
// API Gateway EndPoint
new cdk.CfnOutput(this, 'RestApiEndpoint', {
value: restApi.deploymentStage.urlForPath(),
});
...
참고자료
Amazon Cognito 사용자 풀을 권한 부여자로 사용하여 REST API에 대한 액세스 제어
블로그 릴레이 - CDK 와 Serverless express 사용해 보기